package com.library.service.impl;


import com.library.common.core.domain.BaseEntity;
import com.library.common.core.domain.entity.SysDictData;
import com.library.common.core.text.Convert;
import com.library.domain.*;
import com.library.mapper.*;
import com.library.service.IMbSignRecordService;
import com.library.system.mapper.SysDictDataMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Random;

/**
 * 公众号签到 服务层实现
 *
 * @author null
 * @date 2020-04-23
 * @blame Android Team
 */
@Service
@Slf4j
@SuppressWarnings("all")
public class MbSignRecordServiceImpl implements IMbSignRecordService {
    private SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
    /**
     * 初始、断签积分起始值
     */
    private static final String START_SIGN_NUM = "start_sign_num";

    @Autowired
    private MbSignRecordMapper mbSignRecordMapper;

    @Autowired
    private SysDictDataMapper sysDictDataDao;

    @Autowired
    private MbSignRulesMapper signRulesMapper;

    @Autowired
    private BoMembersMapper membersMapper;

    @Autowired
    private BoIntegralHistoryMapper integralHistoryMapper;

    @Autowired
    private MbGiftConvertMapper mbGiftConvertMapper;

    @Autowired
    private MbSignRulesGiftMapper mbSignRulesGiftMapper;

    @Autowired
    private MbGiftMapper giftMapper;

    /**
     * 查询公众号签到信息
     *
     * @param id 公众号签到ID
     * @return 公众号签到信息
     */
    @Override
    public MbSignRecord selectMbSignRecordById(Long id) {
        return mbSignRecordMapper.selectMbSignRecordById(id);
    }

    /**
     * 查询公众号签到列表
     *
     * @param mbSignRecord 公众号签到信息
     * @return 公众号签到集合
     */
    @Override
    public List<MbSignRecord> selectMbSignRecordList(MbSignRecord mbSignRecord) {
        return mbSignRecordMapper.selectMbSignRecordList(mbSignRecord);
    }

    /**
     * 新增公众号签到
     *
     * @param mbSignRecord 公众号签到信息
     * @return 结果
     */
    @Override
    @Transactional
    public int insertMbSignRecord(MbSignRecord mbSignRecord) throws ParseException, RuntimeException {
        mbSignRecord.setSignInTime(format.parse(format.format(new Date())));
        //获取用户历史签到次数
        List<MbSignRecord> mbSignRecords = selectLastSignRecord(mbSignRecord);
        mbSignRecord.setSignNum(mbSignRecords.size() + 1);
        if (null != mbSignRecords && mbSignRecords.size() > 0) {
            mbSignRecord.setLastSignTime(mbSignRecords.get(0).getSignInTime());
        }
        mbSignRecord.setUninterruptedlySignNum(countUninterruptedlySignNum(mbSignRecords));
        //修改用户积分
        addMembersIntrgral(mbSignRecord, mbSignRecords);
        //随机抽取礼品
        getMbGiftConvert(mbSignRecord, mbSignRecords);
        return mbSignRecordMapper.insertMbSignRecord(mbSignRecord);
    }


    private void getMbGiftConvert(MbSignRecord mbSignRecord, List<MbSignRecord> mbSignRecords) throws RuntimeException {
        MbSignRules signLuckyDraw = isSignLuckyDraw(mbSignRecords);
        if (null != signLuckyDraw) {
            Integer id = signLuckyDraw.getId();
            MbSignRulesGift mbSignRulesGift = new MbSignRulesGift();
            mbSignRulesGift.setRuleId(String.valueOf(id));
            List<MbSignRulesGift> mbSignRulesGifts = mbSignRulesGiftMapper.selectMbSignRulesGiftList(mbSignRulesGift);
            int size = mbSignRulesGifts.size();
            //随机获取中奖概率
            int i = calculateProbability(size, signLuckyDraw);
            if (i != -1) {
                MbGiftConvert giftConvert = new MbGiftConvert();
                giftConvert.setMembersId(mbSignRecord.getMembersId().intValue());
                giftConvert.setSignInTime(new Date());
                giftConvert.setOverdueTime(new Date());
                Integer giftId = mbSignRulesGifts.get(i).getGiftId();
                MbGift mbGift = giftMapper.selectMbGiftById(giftId);
                if (null == mbGift) {
                    log.error("抽奖礼品不存在 MembersId is " + mbSignRecord.getMembersId());
                    return;
                }
                Integer stockNum = mbGift.getStockNum();
                if (stockNum <= 0) {
                    log.error("抽奖礼品数量不足 MembersId is " + mbSignRecord.getMembersId());
                    return;
                }
                mbGift.setStockNum(mbGift.getStockNum() - 1);
                mbGift.setNoConvertNum(mbGift.getNoConvertNum() + 1);
                giftMapper.updateMbGift(mbGift);
                giftConvert.setGiftId(mbSignRulesGifts.get(i).getGiftId());
                giftConvert.setConvertNo(String.valueOf(new Date().getTime()));
                giftConvert.setConvertStatus(MbGiftConvert.NOTCHANGE);
                int a = mbGiftConvertMapper.insertMbGiftConvert(giftConvert);
                BoMembers boMembers = membersMapper.selectBoMembersById(mbSignRecord.getMembersId());
                boMembers.setAwardStatus(BoMembers.STATUS_0);
                int b = membersMapper.updateBoMembers(boMembers);
                if (a <= 0 || b <= 0) {
                    log.error("增加抽奖礼品异常 MembersId is " + mbSignRecord.getMembersId());
                    throw new RuntimeException("增加抽奖礼品异常");
                }

            }
        }
    }

    /**
     * 计算获奖概率
     *
     * @param mbSignRules
     * @return
     */
    private int calculateProbability(int giftNum, MbSignRules mbSignRules) {
        if (giftNum == 0 || mbSignRules.getProbability() == 0) {
            return -1;
        }
        double probability = mbSignRules.getProbability().doubleValue();
        double allNum = giftNum / (probability / 100);
        allNum = allNum * 100; //增加随机概率
        Random random = new Random();
        int i = random.nextInt((int) allNum);
        int value = i / 100;
        if (value < giftNum) {
            return value;
        } else {
            return -1;
        }
    }


    /**
     * 是否需要抽奖
     *
     * @param mbSignRecords 公众号签到信息
     * @return MbSignRules
     */
    private MbSignRules isSignLuckyDraw(List<MbSignRecord> mbSignRecords) {
        MbSignRules mbSignRules = new MbSignRules();
        List<MbSignRules> mbSignRulesList = signRulesMapper.selectMbSignRulesList(mbSignRules);
        int signNum = 1;
        if (null != mbSignRecords && mbSignRecords.size() > 0) {
            signNum = mbSignRecords.get(0).getSignNum().intValue() + 1;
        }
        for (MbSignRules signRules : mbSignRulesList) {
            if (signRules.getCumulativeNum() == signNum) {
                return signRules;
            }
        }
        return null;
    }


    /**
     * 增加用户签到积分
     *
     * @param mbSignRecords
     */
    private void addMembersIntrgral(MbSignRecord mbSignRecord, List<MbSignRecord> mbSignRecords) throws ParseException, RuntimeException {
        BoMembers boMembers = membersMapper.selectBoMembersById(mbSignRecord.getMembersId());
        if (null == boMembers) {
            log.error("select Members is null , members id " + mbSignRecord.getMembersId());
            throw new RuntimeException("用户信息不存在");
        }
        int num = addSignIntegral(mbSignRecords);
        mbSignRecord.setSignIntegral(num);
        boMembers.setAvailableIntegral(boMembers.getAvailableIntegral() + num);
        boMembers.setIntegralLevel(boMembers.getIntegralLevel() + num);
        int a = membersMapper.updateBoMembers(boMembers);
        BoIntegralHistory history = new BoIntegralHistory();
        history.setUserId("system");
        history.setAdjustType("4");
        history.setMembersId(mbSignRecord.getMembersId());
        history.setAdjustNumber(num);
        history.setAfterAdjust(boMembers.getIntegralLevel() + num);
        history.setBeforeAdjust(boMembers.getIntegralLevel());
        history.setAdjustReason("公众号签到");
        int b = integralHistoryMapper.insertBoIntegralHistory(history);
        if (a <= 0 || b <= 0) {
            log.error("update Members is error , members id " + mbSignRecord.getMembersId());
            throw new RuntimeException("修改用户积分失败");
        }
    }


    //签到积分
    private int addSignIntegral(List<MbSignRecord> mbSignRecords) throws ParseException {
        MbSignRules mbSignRules = signRulesMapper.selectContinuousSignRules();
        //首次签到、断签
        if (countUninterruptedlySignNum(mbSignRecords) == 1) {
            int startSignNum = getStartSignNum();
            return startSignNum;
        } else {
            Integer signIntegral = mbSignRecords.get(0).getSignIntegral();
            signIntegral = signIntegral + mbSignRules.getStepLength().intValue();
            if (signIntegral >= mbSignRules.getMaxNum()) {
                return mbSignRules.getMaxNum();
            } else {
                return signIntegral;
            }
        }
    }


    /**
     * 获取初次签到，断签初始值
     *
     * @return
     */
    private int getStartSignNum() {
        List<SysDictData> sysDictData = sysDictDataDao.selectDictDataByType(START_SIGN_NUM);
        if (null == sysDictData || sysDictData.size() == 0) {
            return 1;
        }
        return Integer.valueOf(sysDictData.get(0).getDictValue());
    }


    @Override
    public boolean isSign(MbSignRecord mbSignRecord) throws ParseException {
        mbSignRecord.setSignInTime(format.parse(format.format(new Date())));
        List<MbSignRecord> mbSignRecords = mbSignRecordMapper.selectMbSignRecordList(mbSignRecord);
        if (null == mbSignRecords || mbSignRecords.size() == 0) {
            return true;
        }
        return false;
    }


    /**
     * 查询用户上次签到时间
     *
     * @param mbSignRecord 签到dto
     * @return
     */
    private List<MbSignRecord> selectLastSignRecord(MbSignRecord mbSignRecord) {
        return mbSignRecordMapper.selectMbSignRecordListByMembersId(mbSignRecord.getMembersId().intValue());
    }

    /**
     * 计算连续签到次数
     *
     * @param mbSignRecords 用户签到记录
     * @return
     */
    private static int countUninterruptedlySignNum(List<MbSignRecord> mbSignRecords) throws ParseException {
        if (null == mbSignRecords || mbSignRecords.size() == 0) {
            return 1;
        }
        MbSignRecord signRecord = mbSignRecords.get(0);
        //上次签到时间
        Date signInTime = signRecord.getSignInTime();
        Long day = getDay(signInTime);
        if (day <= 1) {
            return signRecord.getUninterruptedlySignNum() + 1;
        }
        return 1;
    }

    /*
    判读时间差距，两个时间相差多少天，时，分，秒
     */
    public static Long getDay(Date pastTime) {
        DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        Long days = null;
        try {
            Date currentTime = dateFormat.parse(dateFormat.format(new Date()));//现在系统当前时间
            long diff = currentTime.getTime() - pastTime.getTime();
            days = diff / (1000 * 60 * 60 * 24);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return days;
    }


    /**
     * 修改公众号签到
     *
     * @param mbSignRecord 公众号签到信息
     * @return 结果
     */
    @Override
    public int updateMbSignRecord(MbSignRecord mbSignRecord) {
        return mbSignRecordMapper.updateMbSignRecord(mbSignRecord);
    }

    /**
     * 删除公众号签到对象
     *
     * @param ids 需要删除的数据ID
     * @return 结果
     */
    @Override
    public int deleteMbSignRecordByIds(Long[] ids) {
        for (Long id : ids) {
            MbSignRecord mbSignRecord = mbSignRecordMapper.selectMbSignRecordById(id);
            if (null == mbSignRecord)
                continue;
            mbSignRecord.setIsDelete(BaseEntity.DELETE);
            mbSignRecordMapper.updateMbSignRecord(mbSignRecord);
        }
        return BaseEntity.DELETE;
    }

    @Override
    public MbSignRecord theLastSignRecord(Integer membersId) {
        return mbSignRecordMapper.theLastSignRecord(membersId).get(0);
    }

    @Override
    public int theLastSignIntegral(Integer membersId) throws ParseException {
        List<MbSignRecord> mbSignRecords = mbSignRecordMapper.theLastSignRecord(membersId);
        return addSignIntegral(mbSignRecords);
    }


}
